module nazo.array;
/**
 * 配列を拡張する
 * History:
 *          0.0.1 最初の作成
 *          0.0.2 TArr(T).packのbugfix
 *          0.0.3 bindとfilの追加。全てを別々のテンプレートに。
 *          0.0.3.1 bindの調整
 *          0.0.4 newArrの削除
 *          0.0.5 serializeの追加
 *          0.0.5 serializeの削除
 * Authors: Nazo
 * Version: 0.0.5
 * License: Public Domain
 */

///二次元配列を一次元に展開
T[] unpack(T)(T[][] i){
  T[] result;
  uint ptr;
  foreach(T[] t;i){
    result.length=ptr+t.length;
    result[ptr..ptr+t.length]=t[0..$];
    ptr+=t.length;
  }
  return result;
}

///一次元配列を二次元に
T[][] pack(T)(T[] t,int size){
  T[][] result;
  result.length=t.length/size;
  int j;
  for(int i;i<result.length;i++){
    result[i].length=size;
    result[i][0..$]=t[j..j+size];
    j+=size;
  }
  return result;
}
///二次元の二次元目の長さを変更
void twoDimensionLength(T)(inout T[][] t,int size){
  foreach(inout T[] i;t){
    i.length=size;
  }
}

///それぞれの要素をfで変換します。
U[] bind(T,U)(T[] a,U delegate(T) f){
  U[] re;
  re.length=a.length;
  foreach(uint i,T b;a){
    re[i]=f(b);
  }
  return re;
}

///fがtrueを返す要素を返します。
T[] fil(T)(T[] a,bool delegate(T) f){
  T[] re;
  foreach(T b;a){
    if(f(b))
      re~=b;
  }
  return re;
}

///配列aにcが含まれてるか
bool opIn_r(T)(T[] a,T c){
  foreach(T b;a){
    if(b==c)return true;
  }
  return false;
}

class PackException:Exception{
  this(string name){
    super("Pack Exception: "~name);
  }
}

unittest{
  assert(unpack!(ubyte)(cast(ubyte[][])[cast(ubyte[])[0x86]
            ,cast(ubyte[])[0x8D,0x1F]])==cast(ubyte[])[0x86,0x8D,0x1F]);
  assert(pack!(ubyte)(cast(ubyte[])[0x86,0x20,0x8D,0x1F],2)
            ==cast(ubyte[][])[cast(ubyte[])[0x86,0x20],
                              cast(ubyte[])[0x8D,0x1F]]);
}
